package cz.muni.fi.pa165.entity;

import cz.muni.fi.pa165.entity.Package;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;

/**
 * Entity Delivery. Delivery can have one or more packages. It holds info about creation and delivery time, 
 * recipient credentials and delivery boy.
 * 
 * @author <a href="mailto:vramik at redhat.com">Vlastislav Ramik</a>
 */
@Entity
public class Delivery implements Serializable {
    
    private static final long serialVersionUID = 6546541654515L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @OneToMany(fetch= FetchType.EAGER)
    private List<Package> packages;
    
    @Temporal(javax.persistence.TemporalType.TIMESTAMP)
    private Date creationDate;
    
    @Temporal(javax.persistence.TemporalType.TIMESTAMP)
    private Date deliveryDate;
    
    @NotNull
    @OneToOne
    private Employee deliveryBoy;
    
    @NotNull
    @OneToOne
    private Customer customer;
    
    @NotEmpty
    @Size(max = 50, message = "Recipient name must be at most 50 characters long.")
    private String recipientName;
   
    @NotEmpty
    @Size(max = 70, message = "Recipient address must be at most 70 characters long.")
    private String recipientAddress;
    
    @NotEmpty
    @Size(max = 10, message = "Recipient zip must be at most 10 characters long.")
    private String recipientZip;
    
    @NotEmpty
    @Size(max = 20, message = "Recipient city must be at most 20 characters long.")
    private String recipientCity;

    public Long getId() {
        return id;
    }

    /**
     * Sets unique id
     * @param id Delivery id
     * @throws IllegalArgumentException if id was set before method called
     */
    public void setId(Long id) {
        if (this.id != null) {
            throw new IllegalArgumentException("id was already set.");
        }
        this.id = id;
    }

    public Date getCreationDate() {
        if (creationDate == null) {
            return null;
        }
        return (Date) creationDate.clone();
    }

    public void setCreationDate(Date creationDate) {
        if (creationDate != null) {
            this.creationDate = new Date(creationDate.getTime());
        }
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public Employee getDeliveryBoy() {
        return deliveryBoy;
    }

    public void setDeliveryBoy(Employee deliveryBoy) {
        this.deliveryBoy = deliveryBoy;
    }

    public Date getDeliveryDate() {
        if (deliveryDate == null) {
            return null;
        }
        return (Date) deliveryDate.clone();
    }

    public void setDeliveryDate(Date deliveryDate) {
        if (deliveryDate != null) {
            this.deliveryDate = new Date(deliveryDate.getTime());
        }
    }

    public Long getDeliveryNumber() {
        return getId();
    }

    /**
     * 
     * @return list of packages, empty list if attribute is null
     */
    public List<Package> getPackages() {
        if(packages==null) {
            return new ArrayList<Package>();
        }
        return packages;
    }

    public void setPackages(List<Package> packages) {
        this.packages = packages;
    }

    public String getRecipientAddress() {
        return recipientAddress;
    }

    public void setRecipientAddress(String recipientAddress) {
        this.recipientAddress = recipientAddress;
    }

    public String getRecipientCity() {
        return recipientCity;
    }

    public void setRecipientCity(String recipientCity) {
        this.recipientCity = recipientCity;
    }

    public String getRecipientName() {
        return recipientName;
    }

    public void setRecipientName(String recipientName) {
        this.recipientName = recipientName;
    }

    public String getRecipientZip() {
        return recipientZip;
    }

    public void setRecipientZip(String recipientZip) {
        this.recipientZip = recipientZip;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Delivery other = (Delivery) obj;
        if (this.id == null || !this.id.equals(other.id)) {
            return false;
        }
        return true;
    }  

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 23 * hash + (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }

    @Override
    public String toString() {
        return "Delivery{" + "id=" + id + ", packages=" + packages + ", creationDate=" + creationDate + ", deliveryDate=" + deliveryDate + ", deliveryBoy=" + deliveryBoy + ", customer=" + customer + ", recipientName=" + recipientName + ", recipientAddress=" + recipientAddress + ", recipientZip=" + recipientZip + ", recipientCity=" + recipientCity + '}';
    }
}
